home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Tools 2
/
Amiga Tools 2.iso
/
tools
/
jade
/
src
/
x11_eventloop.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-09
|
7KB
|
304 lines
/* x11_eventloop.c -- Eventloop for X11
Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
This file is part of Jade.
Jade is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Jade is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jade; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "jade.h"
#include "jade_protos.h"
#ifdef HAVE_UNIX
# include <sys/types.h>
# include <sys/time.h>
# include <errno.h>
#else
you lose
#endif
_PR VALUE event_loop(void);
static VALUE
handle_event(XEvent *xev)
{
VW *oldvw = curr_vw, *ev_vw;
VALUE result = sym_nil;
/* std_message(curr_vw); */
ev_vw = x11_find_window_view(xev->xany.window);
if(ev_vw)
{
switch(xev->type)
{
u_long code, mods;
case MappingNotify:
XRefreshKeyboardMapping(&xev->xmapping);
break;
case Expose:
if(ev_vw->vw_Flags & VWFF_SLEEPING)
{
/* Guess that the wm uniconified us? */
ev_vw->vw_Flags &= ~VWFF_SLEEPING;
}
if(ev_vw->vw_Flags & VWFF_FORCE_REFRESH)
{
/* Wait until the last Expose then do a total redraw. */
if(xev->xexpose.count == 0)
{
draw_message_line(ev_vw);
ev_vw->vw_Flags |= VWFF_REFRESH_STATUS;
refresh_window(ev_vw);
}
}
else
x11_handle_expose(ev_vw, &xev->xexpose);
if(ev_vw == oldvw)
cursor(ev_vw, CURS_ON);
break;
case ConfigureNotify:
if((ev_vw->vw_WindowSys.ws_Width != xev->xconfigure.width)
|| (ev_vw->vw_WindowSys.ws_Height != xev->xconfigure.height))
{
if(ev_vw == oldvw)
cursor(ev_vw, CURS_OFF);
if((ev_vw->vw_WindowSys.ws_Height != 0)
&& (ev_vw->vw_WindowSys.ws_Height < xev->xconfigure.height))
{
/* Have to clear out the status line. It can be left in
the wrong place. */
CLR_AREA(ev_vw, 0, ev_vw->vw_MessageLineY,
ev_vw->vw_WindowSys.ws_Width, ev_vw->vw_FontY+2);
}
ev_vw->vw_WindowSys.ws_Width = xev->xconfigure.width;
ev_vw->vw_WindowSys.ws_Height = xev->xconfigure.height;
x11_update_dimensions(ev_vw, xev->xconfigure.width, xev->xconfigure.height);
if(ev_vw == oldvw)
cursor(ev_vw, CURS_ON);
}
break;
case ClientMessage:
if((xev->xclient.format == 32)
&& (xev->xclient.data.l[0] == x11_wm_del_win))
{
curr_vw = ev_vw;
if(ev_vw != oldvw)
{
/* Window switch */
undo_distinct();
cursor(oldvw, CURS_OFF);
}
else
cursor(ev_vw, CURS_OFF);
result = cmd_eval_hook2(MKSTR("window-closed-hook"), sym_nil);
if(curr_vw)
{
refresh_world();
cursor(curr_vw, CURS_ON);
}
}
break;
case FocusIn:
if(ev_vw != oldvw)
{
cursor(oldvw, CURS_OFF);
cursor(ev_vw, CURS_ON);
curr_vw = ev_vw;
undo_distinct();
}
break;
case ButtonPress:
case ButtonRelease:
case KeyPress:
code = mods = 0;
translate_event(&code, &mods, xev);
if(mods & EV_TYPE_MASK)
{
curr_vw = ev_vw;
if(oldvw != ev_vw)
{
cursor(oldvw, CURS_OFF);
undo_distinct();
}
result = usekey(xev, code, mods, (ev_vw == oldvw));
}
break;
}
}
return(result);
}
VALUE
event_loop(void)
{
VALUE result = sym_nil;
recurse_depth++;
std_message(curr_vw);
refresh_world_curs();
while(curr_vw)
{
#ifdef HAVE_UNIX
fd_set copy;
struct timeval timeout;
int number, i;
bool refreshp;
#endif
/*
* HERE... Read out all events in Q
*/
while(INT_P || XEventsQueued(x11_display, QueuedAfterReading) > 0)
{
if(INT_P)
result = NULL;
else
{
XEvent ev;
XNextEvent(x11_display, &ev);
result = handle_event(&ev);
}
if(!result)
{
if(throw_value)
{
VALUE tv = throw_value;
VALUE car = VCAR(tv);
throw_value = NULL;
if(car == sym_exit)
{
result = VCDR(tv);
if(recurse_depth > 0)
goto end;
}
else if((car == sym_top_level) && (recurse_depth == 0))
result = VCDR(tv);
else if(car == sym_quit)
goto end;
else if(car == sym_user_interrupt)
{
handle_error(car, sym_nil);
result = sym_nil;
}
else if(car == sym_error)
{
handle_error(VCAR(VCDR(tv)), VCDR(VCDR(tv)));
result = sym_nil;
}
else if(recurse_depth == 0)
{
result = sym_nil;
handle_error(sym_no_catcher, LIST_1(car));
}
else
{
throw_value = tv;
goto end;
}
}
else
result = sym_nil;
}
if(!curr_vw)
goto end;
#if 0
std_message(curr_vw);
if(curr_vw->vw_Flags & VWFF_REFRESH_STATUS)
{
refresh_message(curr_vw);
curr_vw->vw_Flags &= ~VWFF_REFRESH_STATUS;
}
#endif
}
# ifdef HAVE_SUBPROCESSES
if(proc_notification())
{
std_message(curr_vw);
refresh_world_curs();
}
# endif
XFlush(x11_display);
#ifdef HAVE_UNIX
copy = x11_fd_read_set;
timeout.tv_sec = EVENT_TIMEOUT_LENGTH;
timeout.tv_usec = 0;
/* Don't want select() to restart after a SIGCHLD; there may be
a notification to dispatch. */
# ifdef HAVE_SUBPROCESSES
sigchld_restart(FALSE);
# endif
number = select(FD_SETSIZE, ©, NULL, NULL, &timeout);
# ifdef HAVE_SUBPROCESSES
sigchld_restart(TRUE);
# endif
refreshp = FALSE;
if(number > 0)
{
/*
* no need to test first 3 descriptors
*/
i = 3;
while(number > 0)
{
if(FD_ISSET(i, ©))
{
number--;
if(x11_fd_read_action[i])
{
x11_fd_read_action[i](i);
refreshp = TRUE;
}
}
i++;
}
}
else if(number == 0)
{
/* A timeout; do one of:
Print the current key-prefix
Auto-save a buffer
GC if enough data allocated
Run the `idle-hook' */
if(print_event_prefix() || auto_save_buffers())
refreshp = TRUE;
else if(data_after_gc > idle_gc_threshold)
{
/* nothing was saved so try a GC */
cmd_garbage_collect(sym_t);
}
else
{
VALUE hook = cmd_symbol_value(sym_idle_hook, sym_t);
if(!VOIDP(hook) && !NILP(hook))
{
cmd_eval_hook2(sym_idle_hook, sym_nil);
refreshp = TRUE;
}
}
}
#else
whatever you like...
#endif /* HAVE_UNIX */
if(refreshp)
{
std_message(curr_vw);
refresh_world_curs();
}
}
end:
recurse_depth--;
return(result);
}